#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "db.h"
#include "structures.h"
#include "privilege.h"

static int hasPrivilegeForSector(t_privilege **, int, t_privilege *);
static t_users * addAll(t_users *, t_users *);
static int isPresent(t_users *, char *);

int
hasAnyPrivilege(char * user, char * title) {
	int i;
	
	/* Get from DB sectors and minimum level of 
	 * privilege for this document. */
	t_privileges * documentSectors = (t_privileges *) getSectorsForTitle(title);
	/* Get from DB sectors and minimum level of
	 * privilege for this user. */
	t_privileges * userSectors = (t_privileges *) getSectorsForUser(user);

	if (documentSectors == NULL || userSectors == NULL) {
		return 0;
	}

	for (i = 0; i < documentSectors->size; i++) {
		if (hasPrivilegeForSector(userSectors->sectors, userSectors->size, documentSectors->sectors[i])) {
			return 1;
		}
	}

	return 0;
}

int
hasPrivilege(char * user, char * title, char * sectorname) {
	int i, j;
	t_privileges * userSectors = (t_privileges *) getSectorsForUser(user);
	t_privileges * documentSectors = (t_privileges *) getSectorsForTitle(title);

	if (userSectors == NULL || documentSectors == NULL) {
		return 0;
	}
//printf("user: %s\ntitle: %s\n%s\n", user, title, sectorname);
	for (i = 0; i < userSectors->size; i++) {
		if (strcmp(sectorname, userSectors->sectors[i]->name) == 0) {
			int userLevel = userSectors->sectors[i]->order;
			for (j = 0; j < documentSectors->size; j++) {
				if (strcmp(sectorname, documentSectors->sectors[i]->name) == 0) {
					int docLevel = documentSectors->sectors[i]->order;
					printf("user: %d\ndoc: %d\n", userLevel, docLevel);
					if (userLevel >= docLevel) {
						return 1;
					} else {
						return 0;
					}
				}
			}
		}
	}

	return 0;
}

static int
hasPrivilegeForSector(t_privilege ** userSectors, int size, t_privilege * sector) {
	int shareSector;
	int hasLevel;
	int i;

	for (i = 0; i < size; i++) {
		shareSector = (strcmp(userSectors[i]->name, sector->name) == 0);
		hasLevel = (userSectors[i]->order >= sector->order);
		
		if (shareSector && hasLevel) {
			return 1;
		}
	}

	return 0;
}

t_users *
getSamePrivilegeUsers(char * user) {
	t_users * ret;
	int i, j;
	int maxLevel;

	ret = (t_users *) malloc(sizeof(t_users));
	if (ret == NULL) {
		fprintf(stderr, "Error while allocating memory\n");
		return NULL;
	}
	ret->size = 0;
	ret->maxSize = MAX_SIZE;
	ret->users = (t_user **) malloc(sizeof(t_user *) * MAX_SIZE);
	if (ret->users == NULL) {
		fprintf(stderr, "Error while allocating memory\n");
		return NULL;
	}

	t_privileges * userSectors = getSectorsForUser(user);
	if (userSectors == NULL) {
		return ret;
	}

	for (i = 0; i < userSectors->size; i++) {
		t_users * users = getUsersForSector(userSectors->sectors[i]->name, userSectors->sectors[i]->order);
		addAll(ret, users);
		maxLevel = getMaxLevel(userSectors->sectors[i]->name);
		for (j = userSectors->sectors[i]->order + 1; j <= maxLevel; j++) {
			t_users * lower = getUsersForSector(userSectors->sectors[i]->name, j);
			addAll(ret, lower);
		}
	}

	return ret;	
}

static t_users *
addAll(t_users * all, t_users * new) {
	int i;

	if ((all->size == all->maxSize) || ((all->size + new->size) >= all->maxSize)) {
		t_users * aux = malloc(sizeof(t_users));
		if (aux == NULL) {
			fprintf(stderr, "Error while allocating memory\n");
			return NULL;
		}
		aux->size = all->size;
		aux->maxSize = all->maxSize * 2;
		aux->users = (t_user **) malloc(sizeof(t_user *) * all->maxSize);
		if (aux->users == NULL) {
			fprintf(stderr, "Error while allocating memory\\n");
			return NULL;
		}

		for (i = 0; i < all->size; i++) {
			aux->users[i]->username = all->users[i]->username;
		}

		all = aux;	
	}

	for (i = 0; i < new->size; i++) {
		if (!isPresent(all, new->users[i]->username)) { 
			t_user * tUser = (t_user *) malloc(sizeof(t_user));
			if (tUser == NULL) {
				fprintf(stderr, "Error while allocating memory\n");
				return NULL;
			}
			tUser->username = (char *) malloc(sizeof(char) * 9);
			if (tUser->username == NULL) {
				fprintf(stderr, "Error while allocating memory\n");
				return NULL;
			}

			strcpy(tUser->username, new->users[i]->username);
			all->users[all->size] = tUser;
			all->size++;
		}
	}

	return all;
}

static int
isPresent(t_users * all, char * current) {
	int i;

	for (i = 0; i < all->size; i++) {
		if (strcmp(all->users[i]->username, current) == 0) {
			return 1;
		}
	}

	return 0;
}


char *
getPrivilege(char * title, char * sector) {
	return getLevelForDocumentSector(title, sector);
}

char *
getPublicKey(char * user) {
	return getUserKey(user);
}

char *
getPrivilegeForUserSector(char * user, char * sector) {
	return getPrivilegeUserSector(user, sector);
}
